/*
 * Unidata Platform
 * Copyright (c) 2013-2020, UNIDATA LLC, All rights reserved.
 *
 * Commercial License
 * This version of Unidata Platform is licensed commercially and is the appropriate option for the vast majority of use cases.
 *
 * Please see the Unidata Licensing page at: https://unidata-platform.com/license/
 * For clarification or additional options, please contact: info@unidata-platform.com
 * -------
 * Disclaimer:
 * -------
 * THIS SOFTWARE IS DISTRIBUTED "AS-IS" WITHOUT ANY WARRANTIES, CONDITIONS AND
 * REPRESENTATIONS WHETHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION THE
 * IMPLIED WARRANTIES AND CONDITIONS OF MERCHANTABILITY, MERCHANTABLE QUALITY,
 * FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, NON-INFRINGEMENT, PERFORMANCE AND
 * THOSE ARISING BY STATUTE OR FROM CUSTOM OR USAGE OF TRADE OR COURSE OF DEALING.
 */
package org.unidata.mdm.job.reindex.service.impl;

import java.util.UUID;

import org.apache.commons.lang3.tuple.Triple;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.unidata.mdm.core.service.MetaModelService;
import org.unidata.mdm.core.service.job.JobCommonParameters;
import org.unidata.mdm.core.type.keys.LSN;
import org.unidata.mdm.data.context.UpsertRequestContext;
import org.unidata.mdm.job.reindex.configuration.ReindexJobConfigurationConstants;
import org.unidata.mdm.meta.configuration.Descriptors;
import org.unidata.mdm.meta.type.instance.DataModelInstance;

/**
 * @author Denis Kostovarov
 */
@Component("reindexDataJobItemProcessor")
@StepScope
public class ReindexDataJobDataItemProcessor implements ItemProcessor<Triple<LSN, UUID, String>, UpsertRequestContext> {
    /**
     * Skip data quality
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_SKIP_DQ + "]}")
    private boolean skipDq;
    /**
     * Suppress system checks.
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_SKIP_CONSISTENCY_CHECK + "] ?: true }")
    private boolean skipConsistencyChecks;
    /**
     * Clean types
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_CLEAN_INDEXES + "] ?: false }")
    private boolean indexesAreEmpty;
    /**
     * Enable jms notifications
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_SKIP_NOTIFICATIONS + "] ?: false}")
    private boolean skipNotifications;
    /**
     * Job operation id
     */
    @Value("#{jobParameters[" + JobCommonParameters.PARAM_OPERATION_ID + "]}")
    private String operationId;
    /**
     * If true, record's data will be reindexed
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_REINDEX_RECORDS + "] ?: false}")
    private boolean jobReindexRecords;
    /**
     * If true, rels will be reindexed
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_REINDEX_RELATIONS + "] ?: false}")
    private boolean jobReindexRelations;
    /**
     * If true, classifiers will be reindexed
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_REINDEX_CLASSIFIERS + "] ?: false}")
    private boolean jobReindexClassifiers;
    /**
     * If true, matching data will be reindexed
     */
    @Value("#{jobParameters[" + ReindexJobConfigurationConstants.PARAM_REINDEX_MATCHING + "] ?: false}")
    private boolean jobReindexMatching;
    /**
     * If true, record's data will be reindexed
     */
    @Value("#{stepExecutionContext[" + ReindexJobConfigurationConstants.PARAM_REINDEX_RECORDS + "] ?: false}")
    private boolean stepReindexRecords;
    /**
     * If true, rels will be reindexed
     */
    @Value("#{stepExecutionContext[" + ReindexJobConfigurationConstants.PARAM_REINDEX_RELATIONS + "] ?: false}")
    private boolean stepReindexRelations;
    /**
     * If true, classifiers will be reindexed
     */
    @Value("#{stepExecutionContext[" + ReindexJobConfigurationConstants.PARAM_REINDEX_CLASSIFIERS + "] ?: false}")
    private boolean stepReindexClassifiers;
    /**
     * If true, matching data will be reindexed
     */
    @Value("#{stepExecutionContext[" + ReindexJobConfigurationConstants.PARAM_REINDEX_MATCHING + "] ?: false}")
    private boolean stepReindexMatching;
    /**
     * Entity name
     */
    @Value("#{stepExecutionContext[" + JobCommonParameters.PARAM_ENTITY_NAME + "]}")
    private String entityName;
    /**
     * Meta model service.
     */
    @Autowired
    private MetaModelService metaModelService;

    @Override
    public UpsertRequestContext process(Triple<LSN, UUID, String> row) throws Exception {

        LSN lsn = row.getLeft();
        UUID etalonId = row.getMiddle();
        String name = row.getRight();

        // record from already removed registry
        DataModelInstance i = metaModelService.instance(Descriptors.DATA);
        if (!i.isRegister(name) && !i.isLookup(name)) {
            return null;
        }

        return UpsertRequestContext.builder()
                .recalculateWholeTimeline(true)
                .skipConsistencyChecks(skipConsistencyChecks)
                .skipCleanse(skipDq)
                .operationId(operationId)
                .skipIndexDrop(indexesAreEmpty)
                .etalonKey(etalonId.toString())
                .entityName(name)
                .lsn(lsn)
                .build();
    }

    public void setOperationId(String operationId) {
        this.operationId = operationId;
    }

    public void setEntityName(String entityName) {
        this.entityName = entityName;
    }

    public void setJobReindexRecords(Boolean reindexRecords) {
        this.jobReindexRecords = reindexRecords;
    }

    public void setJobReindexRelations(Boolean reindexRelations) {
        this.jobReindexRelations = reindexRelations;
    }

    public void setSkipDq(boolean skipDq) {
        this.skipDq = skipDq;
    }
}
